package com.jhgsys.internal.system.controller;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jhgsys.internal.common.annotation.Log;
import com.jhgsys.internal.common.controller.BaseController;
import com.jhgsys.internal.common.entity.FebsConstant;
import com.jhgsys.internal.common.entity.FebsResponse;
import com.jhgsys.internal.common.entity.MenuTree;
import com.jhgsys.internal.common.entity.QueryRequest;
import com.jhgsys.internal.common.exception.FebsException;
import com.jhgsys.internal.dict.entity.DictItem;
import com.jhgsys.internal.dict.service.IDictItemService;
import com.jhgsys.internal.system.dto.RoleDto;
import com.jhgsys.internal.system.dto.TenantDto;
import com.jhgsys.internal.system.entity.Menu;
import com.jhgsys.internal.system.entity.Role;
import com.jhgsys.internal.system.service.IMenuService;
import com.jhgsys.internal.system.service.IRoleService;
import com.jhgsys.internal.system.service.ITenantService;
import com.wuwenze.poi.ExcelKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.*;
import java.util.stream.Collectors;

import static com.jhgsys.internal.common.constant.DictCodeConstant.SYSTEM_ROLE_TYPE;

/**
 * @author MrBird
 */
@Slf4j
@RestController
@RequestMapping("role")
public class RoleController extends BaseController {

    @Autowired
    private IRoleService roleService;

    @Autowired
    private ITenantService tenantService;

    /**
     * 菜单
     */
    @Autowired
    private IMenuService menuService;

    @Autowired
    private IDictItemService dictItemService;

    /**
     * 查询有权限的角色
     *
     * @param role
     * @return
     */
    @GetMapping
    @RequiresPermissions("role:view")
    public FebsResponse getAllRoles(Role role) {
        List<Role> roleList = roleService.findRoles(role);
        return new FebsResponse().success().data(roleList);
    }

    private boolean existsRole(Role role, List<Role> roleList) {
        if (roleList == null || roleList.size() == 0) {
            return false;
        }
        Optional<Role> first = roleList.stream().filter(r -> role.getRoleId().equals(r.getRoleId())).findFirst();
        return (first.isPresent());
    }

    @GetMapping("list")
    @RequiresPermissions("role:view")
    public FebsResponse roleList(Role role, QueryRequest request) {
        log.info("当前用户未分配公司{}", getCurrentUser().toString());
        //总公司看全部分公司只能查对应公司角色
        if (StringUtils.isBlank(role.getTenantId())) {
            role.setTenantId(getCurrentTenantId());
        }
        Map<String, Object> dataTable = getDataTable(this.roleService.findRoles(role, request));
        return new FebsResponse().success().data(dataTable);
    }

    @Log("新增角色")
    @PostMapping
    @RequiresPermissions("role:add")
    public FebsResponse addRole(@Valid RoleDto role) throws FebsException {
        try {
            if (StringUtils.isBlank(role.getTenantId())) {
                if (hasHeadCompanyRole()) {
                    return new FebsResponse().fail().message("所属公司不能为空！");
                } else {
                    role.setTenantId(getCurrentTenantId());
                }

            }
            role.setStatus("1");
            role.setCreatedBy(getCurrentUser().getUserName());
            Role queryData = this.roleService.getOne(new LambdaQueryWrapper<Role>()
                    .eq(Role::getTenantId, role.getTenantId())
                    .eq(Role::getRoleName, role.getRoleName())
                    .eq(Role::getDeletedFlg, FebsConstant.VALID));
            if (ObjectUtils.isNotEmpty(queryData)) {
                return new FebsResponse().fail().message("角色名称已存在！");
            }
            this.roleService.createRole(role);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "新增角色失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    @Log("删除角色")
    @GetMapping("delete/{roleIds}")
    @RequiresPermissions("role:delete")
    public FebsResponse deleteRoles(@NotBlank(message = "{required}") @PathVariable String roleIds) throws FebsException {
        try {
            // 获取当前用户
            Role role = new Role();
            role.setDeletedBy(getCurrentUser().getUserName());
            role.setDeletedTime(new Date());
            role.setDeletedFlg(FebsConstant.INVALID);
            this.roleService.updateRoleDeletedFlg(roleIds, role);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "删除角色失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    @Log("修改角色")
    @PostMapping("update")
    @RequiresPermissions("role:update")
    public FebsResponse updateRole(RoleDto role) throws FebsException {
        try {
            if (StringUtils.isBlank(role.getRoleId())) {
                return new FebsResponse().fail().message("角色Id不能为空！");
            }
            if (StringUtils.isBlank(role.getTenantId())) {
                return new FebsResponse().fail().message("角色归属公司不能为空！");
            }
            Role queryData = this.roleService.getOne(new LambdaQueryWrapper<Role>()
                    .eq(Role::getTenantId, role.getTenantId())
                    .eq(Role::getRoleName, role.getRoleName())
                    .eq(Role::getDeletedFlg, FebsConstant.VALID));
            if (ObjectUtils.isNotEmpty(queryData) && !role.getRoleId().equals(queryData.getRoleId())) {
                return new FebsResponse().fail().message("角色名称已存在！");
            }

            // 获取当前用户
            role.setUpdatedBy(getCurrentUser().getUserName());
            this.roleService.updateRole(role);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "修改角色失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    @GetMapping("excel")
    @RequiresPermissions("role:export")
    public void export(QueryRequest queryRequest, Role role, HttpServletResponse response) throws FebsException {
        try {
            List<RoleDto> roles = this.roleService.findRoles(role, queryRequest).getRecords();
            ExcelKit.$Export(Role.class, response).downXlsx(roles, false);
        } catch (Exception e) {
            String message = "导出Excel失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }


    /**
     * 根据公司id获取公司对应菜单权限
     * 总公司用户 新增时默认获取所有
     * 编辑 或者 新增选择不同的分公司，则返回默认分公司的菜单权限
     * 分公司用户 新增 编辑 默认返回该用户所属分公司对应的菜单权限
     *
     * @param tenantId
     * @return
     * @throws FebsException
     */
    @GetMapping("tenantTree")
    public FebsResponse getTenantMenuTree(@RequestParam("tenantId") String tenantId,
                                          @RequestParam("roleId") String roleId) throws FebsException {
        try {
            RoleDto role = roleService.findRoleByRoleId(roleId);
            TenantDto tenantDto = tenantService.findTenantByTenantId(tenantId);
            MenuTree<Menu> menus = new MenuTree<>();
            if (null != tenantDto && "1".equals(tenantDto.getTenantCategory())) {
                Menu menuParam = new Menu();
                menuParam.setStatus("1");
                menuParam.setDeletedFlg(FebsConstant.VALID);
                menus = this.menuService.findMenus(menuParam);

            } else {
                menus = this.menuService.findChildTenantMenuTree();
            }
            if (role != null && StringUtils.isNotBlank(role.getMenuIds())) {
                initCheckMenuTree(Arrays.asList(role.getMenuIds().split(",")), menus.getChilds());
            }
            return new FebsResponse().success().data(menus.getChilds());
        } catch (Exception e) {
            String message = "获取菜单树失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    private void initCheckMenuTree(List<String> menuIds, List<MenuTree<Menu>> menus) {
        if (CollUtil.isNotEmpty(menus)) {
            for (MenuTree<Menu> menu : menus) {
                if (menuIds.contains(menu.getId())) {
                    menu.setChecked(true);
                }
                if (CollUtil.isNotEmpty(menu.getChilds())) {
                    initCheckMenuTree(menuIds, menu.getChilds());
                }
            }
        }
    }


    @Log("修改角色状态")
    @GetMapping("updateRoleStatus")
    @RequiresPermissions("role:update")
    public FebsResponse updateRoleStatus(Role role) throws FebsException {
        try {
            if (StringUtils.isBlank(role.getRoleId())) {
                throw new FebsException("角色Id不能为空");
            }
            if (StringUtils.isBlank(role.getStatus())) {
                throw new FebsException("角色状态不能为空");
            }
            Role updateRole = new Role();
            updateRole.setRoleId(role.getRoleId());
            updateRole.setStatus(role.getStatus());
            roleService.updateById(updateRole);
            return new FebsResponse().success();
        } catch (Exception e) {
            String message = "修改角色失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }

    @Log("根据公司Id获取对应公司角色列表")
    @GetMapping("getRoleListByTenantId")
    @RequiresPermissions("user:add")
    public FebsResponse getRoleListByTenantId(Role role) throws FebsException {
        try {
            if (StringUtils.isBlank(role.getTenantId())) {
                throw new FebsException("公司Id不能为空");
            }
            List<Role> roleList = roleService.findRoles(role);
            return new FebsResponse().success().data(roleList);
        } catch (Exception e) {
            String message = "修改角色失败";
            log.error(message, e);
            throw new FebsException(message);
        }
    }


}
